<?php
namespace Illuminate\Support;

use Closure;
use InvalidArgumentException;

abstract class Manager {
    protected $app;
    protected $customCreators = [];
    protected $drivers = [];

    public function __construct($app) {
        $this->app = $app;
    }

    abstract public function getDefaultDriver();

    public function driver($driver = null) {
        $driver = $driver ?: $this->getDefaultDriver();

        if ( is_null($driver) ) {
            throw new InvalidArgumentException(sprintf(
                'Unable to resolve NULL driver for [%s].', static::class
            ));
        }

        if ( ! isset($this->drivers[$driver]) ) {
            $this->drivers[$driver] = $this->createDriver($driver);
        }

        return $this->drivers[$driver];
    }
    protected function createDriver($driver) {
        if ( isset($this->customCreators[$driver]) ) {
            return $this->callCustomCreator($driver);
        } else {
            $method = 'create'.Str::studly($driver).'Driver';

            if ( method_exists($this, $method) ) return $this->$method();
        }
        throw new InvalidArgumentException("Driver [$driver] not supported.");
    }

    protected function callCustomCreator($driver) {
        return $this->customCreators[$driver]($this->app);
    }

    public function extend($driver, Closure $callback) {
        $this->customCreators[$driver] = $callback;

        return $this;
    }

    public function getDrivers() { // 所有驱动
        return $this->drivers;
    }

    public function __call($method, $parameters) {
        return $this->driver()->$method(...$parameters);
    }
}
